package craky.keeper.skin;

import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Iterator;

import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.border.EmptyBorder;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicMenuUI;

import craky.component.JImagePane;
import craky.componentc.CRootPaneUI;
import craky.componentc.JCSlider;
import craky.componentc.JCToggleButton;
import craky.keeper.KeeperApp;
import craky.keeper.util.KeeperUtil;
import craky.layout.LineLayout;
import craky.util.Config;
import craky.util.UIUtil;

public class SkinMenu extends JMenu {
	private static final long serialVersionUID = -2020810008867284350L;
	private static final Icon ICON = KeeperUtil.getIcon("skin_button_icon.png");

	private static final Image ROLLOVER_IMAGE = KeeperUtil.getImage(
			"common_button_rollover_bg.png", true);

	private static final Image PRESSED_IMAGE = KeeperUtil.getImage(
			"skin_button_pressed_bg.png", true);
	private KeeperApp keeper;
	private Config config;
	private SkinMgr skinMgr;
	private JImagePane mainPane;
	private JImagePane skinDispalyPane;
	private JImagePane skinListPane;
	private JImagePane modeDisplayPane;
	private DeleteConfirmPane confirmPane;
	private SkinUnit[] units;
	private JPopupMenu popup;
	private CardLayout mainCardLayout;
	private CardLayout skinDispalyCardLayout;
	private Rectangle skinListBounds;

	public SkinMenu(KeeperApp keeper) {
		setUI(new SkinMenuUI());
		this.keeper = keeper;
		this.config = keeper.getConfig();
		this.skinMgr = new SkinMgr(keeper, this);
		this.units = new SkinUnit[14];
		setPreferredSize(new Dimension(20, 20));
		initUI();
	}

	private void initUI() {
		this.popup = getPopupMenu();
		this.mainPane = new JImagePane(
				KeeperUtil.getImage("skin_popup_bg.png"), "Center");
		this.confirmPane = new DeleteConfirmPane(this.skinMgr);
		this.skinDispalyPane = new JImagePane(
				KeeperUtil.getImage("skin_list_bg.png"), "Center");
		this.skinListPane = new JImagePane(
				KeeperUtil.getImage("skin_unit_bg.png"), "Center");
		this.modeDisplayPane = new JImagePane();
		setToolTipText("更改外观");
		setOpaque(false);
		setFocusable(false);
		setBorder(new EmptyBorder(0, 0, 0, 0));
		setMargin(new Insets(0, 0, 0, 0));
		setDelay(200);
		setIconTextGap(0);
		setBorderPainted(false);
		setRolloverEnabled(true);
		this.confirmPane.setName("Dialog");
		this.mainPane.setName("Main");
		this.mainPane.setImageOnly(true);
		this.mainPane.setBorder(new EmptyBorder(0, 0, 0, 0));
		this.mainPane.setLayout(new LineLayout(0, 0, 0, 0, 0, 10, 10, 1));
		this.skinDispalyPane.setImageOnly(true);
		this.skinDispalyPane.setPreferredSize(new Dimension(236, 97));
		this.skinDispalyPane.setBorder(new EmptyBorder(2, 2, 2, 2));
		this.skinDispalyPane
				.setLayout(this.skinDispalyCardLayout = new CardLayout());
		this.skinListPane.setImageOnly(true);
		this.skinListPane.setName("SkinList");
		this.skinListPane.setBorder(new EmptyBorder(5, 8, 5, 8));
		this.skinListPane.setLayout(new GridLayout(2, 7, 1, 1));
		this.skinListPane.setFilledBorderArea(true);
		this.modeDisplayPane.setImageOnly(true);
		this.modeDisplayPane.setName("ModeDispaly");
		this.modeDisplayPane.setBorder(new EmptyBorder(0, 0, 0, 0));
		this.popup.setOpaque(false);
		this.popup.setBorder(new EmptyBorder(0, 0, 0, 0));
		this.popup.setBorderPainted(false);
		this.popup.setFocusable(false);
		this.popup.setLayout(this.mainCardLayout = new CardLayout());
		this.popup.setPreferredSize(new Dimension(236, 152));
		this.popup.addPopupMenuListener(this.skinMgr);
		this.skinDispalyPane
				.add(this.skinListPane, this.skinListPane.getName());
		this.skinDispalyPane.add(this.modeDisplayPane,
				this.modeDisplayPane.getName());
		this.mainPane.add(this.skinDispalyPane, "Start");
		this.mainPane.add(createModePane(), "Start");
		this.mainPane.add(createAlphaPane(), "MiddleFill");
		this.popup.add(this.mainPane, this.mainPane.getName());
		this.popup.add(this.confirmPane, this.confirmPane.getName());
		this.skinDispalyCardLayout.show(this.skinDispalyPane,
				this.skinListPane.getName());
		initSkinUnits();
		cacheSkinListBounds();
	}

	private void cacheSkinListBounds() {
		Dimension parentSize = this.skinDispalyPane.getPreferredSize();
		Insets parentInsets = this.skinDispalyPane.getInsets();
		Insets insets = this.skinListPane.getInsets();
		int width = parentSize.width - parentInsets.left - parentInsets.right
				- insets.left - insets.right;
		int height = parentSize.height - parentInsets.top - parentInsets.bottom
				- insets.top - insets.bottom;
		this.skinListBounds = new Rectangle(insets.left, insets.top, width,
				height);
	}

	private void initSkinUnits() {
		int length = this.units.length;

		for (int i = 0; i < length; i++) {
			this.units[i] = new SkinUnit(this.keeper, this.skinMgr);
			this.skinListPane.add(this.units[i]);
		}

		this.units[(length - 1)].setLast(true);
		resetSkins();
	}

	public void resetSkins() {
		Iterator<Skin> skins = this.keeper.getAllSkins().values().iterator();

		int index = 1;

		while (index < this.units.length) {
			Skin skin = skins.hasNext() ? (Skin) skins.next() : null;

			if ((skin != null) && (skin.isDefault())) {
				continue;
			}

			this.units[(index++)].setSkin(skin);
		}

		this.units[0].setSkin(this.keeper.getSkin("默认皮肤"));
	}

	private JPanel createModePane() {
		JPanel modePane = new JPanel(new GridLayout(1, 3));
		ButtonGroup group = new ButtonGroup();
		JCToggleButton btnFill = new JCToggleButton();
		JCToggleButton btnTiled = new JCToggleButton();
		JCToggleButton btnScaled = new JCToggleButton();
		HashMap<String, JCToggleButton> buttonMap = new HashMap<String, JCToggleButton>();
		modePane.setBorder(new EmptyBorder(0, 4, 1, 4));
		modePane.setPreferredSize(new Dimension(236, 40));
		modePane.setOpaque(false);
		btnFill.setFocusable(false);
		btnFill.setToolTipText("填充");
		btnFill.setImage(KeeperUtil.getImage("skin_fill_small.png", true));
		btnFill.setRolloverImage(KeeperUtil.getImage("skin_fill_rollover.png",
				true));
		btnFill.setSelectedImage(KeeperUtil.getImage("skin_fill_sel.png", true));
		btnFill.putClientProperty("BigImage",
				KeeperUtil.getImage("skin_fill_big.png", true));
		btnFill.putClientProperty("EventKey", "SkinModePreview");
		btnFill.putClientProperty("SkinModeValue",
				CRootPaneUI.ImageDisplayMode.FILL);
		btnFill.addMouseListener(this.skinMgr);
		btnTiled.setFocusable(false);
		btnTiled.setToolTipText("平铺");
		btnTiled.setImage(KeeperUtil.getImage("skin_tiled_small.png", true));
		btnTiled.setRolloverImage(KeeperUtil.getImage(
				"skin_tiled_rollover.png", true));
		btnTiled.setSelectedImage(KeeperUtil.getImage("skin_tiled_sel.png",
				true));
		btnTiled.putClientProperty("BigImage",
				KeeperUtil.getImage("skin_tiled_big.png", true));
		btnTiled.putClientProperty("EventKey", "SkinModePreview");
		btnTiled.putClientProperty("SkinModeValue",
				CRootPaneUI.ImageDisplayMode.TILED);
		btnTiled.addMouseListener(this.skinMgr);
		btnScaled.setFocusable(false);
		btnScaled.setToolTipText("拉伸");
		btnScaled.setImage(KeeperUtil.getImage("skin_scaled_small.png", true));
		btnScaled.setRolloverImage(KeeperUtil.getImage(
				"skin_scaled_rollover.png", true));
		btnScaled.setSelectedImage(KeeperUtil.getImage("skin_scaled_sel.png",
				true));
		btnScaled.putClientProperty("BigImage",
				KeeperUtil.getImage("skin_scaled_big.png", true));
		btnScaled.putClientProperty("EventKey", "SkinModePreview");
		btnScaled.putClientProperty("SkinModeValue",
				CRootPaneUI.ImageDisplayMode.SCALED);
		btnScaled.addMouseListener(this.skinMgr);
		buttonMap.put(CRootPaneUI.ImageDisplayMode.FILL.toString(), btnFill);
		buttonMap.put(CRootPaneUI.ImageDisplayMode.TILED.toString(), btnTiled);
		buttonMap
				.put(CRootPaneUI.ImageDisplayMode.SCALED.toString(), btnScaled);
		buttonMap.get(this.config.getProperty("Skin_Mode",
				"FILL")).setSelected(true);
		btnFill.addActionListener(this.skinMgr);
		btnTiled.addActionListener(this.skinMgr);
		btnScaled.addActionListener(this.skinMgr);
		group.add(btnFill);
		group.add(btnTiled);
		group.add(btnScaled);
		modePane.add(btnFill);
		modePane.add(btnTiled);
		modePane.add(btnScaled);
		return modePane;
	}

	private JPanel createAlphaPane() {
		int bgAlphaValue = (int) (Float.valueOf(
				this.config.getProperty("Skin_Alpha", "0.50")).floatValue() * 100.0F);
		int winAlphaValue = (int) (Float.valueOf(
				this.config.getProperty("Win_Alpha", "1.0")).floatValue() * 100.0F);
		JPanel alphaPane = new JPanel(new GridLayout(1, 2));
		JCSlider bgAlphaSlider = new JCSlider(0, 0, 100, bgAlphaValue);
		JCSlider winAlphaSlider = new JCSlider(0, 20, 100, winAlphaValue);
		alphaPane.setBorder(new EmptyBorder(0, 4, 2, 3));
		alphaPane.setOpaque(false);
		bgAlphaSlider.setToolTipText("皮肤透明");
		bgAlphaSlider.setMiniMode(true);
		bgAlphaSlider.putClientProperty("EventKey", "SkinAlphaChanged");
		bgAlphaSlider.addChangeListener(this.skinMgr);
		bgAlphaSlider.addMouseListener(this.skinMgr);
		winAlphaSlider.setToolTipText("窗体透明");
		winAlphaSlider.setMiniMode(true);
		winAlphaSlider.putClientProperty("EventKey", "WinAlphaChanged");
		winAlphaSlider.addChangeListener(this.skinMgr);
		winAlphaSlider.addMouseListener(this.skinMgr);
		alphaPane.add(bgAlphaSlider);
		alphaPane.add(winAlphaSlider);
		return alphaPane;
	}

	@Override
	protected void paintComponent(Graphics g) {
		int width = getWidth();
		int height = getHeight();
		int iconWidth = ICON.getIconWidth();
		int iconHeight = ICON.getIconHeight();

		if (getModel().isSelected()) {
			UIUtil.paintImage(g, PRESSED_IMAGE, new Insets(2, 2, 2, 2),
					new Rectangle(0, 0, width, height), this);
		} else if (getModel().isRollover()) {
			UIUtil.paintImage(g, ROLLOVER_IMAGE, new Insets(2, 2, 2, 2),
					new Rectangle(0, 0, width, height), this);
		}

		ICON.paintIcon(this, g, (width - iconWidth) / 2,
				(height - iconHeight) / 2);
	}

	public void modePreview(Image image, boolean hidden) {
		if (hidden) {
			this.skinDispalyCardLayout.show(this.skinDispalyPane,
					this.skinListPane.getName());
		} else {
			this.modeDisplayPane.setImage(image);
			this.skinDispalyCardLayout.show(this.skinDispalyPane,
					this.modeDisplayPane.getName());
		}
	}

	public Rectangle getSkinListBounds() {
		return this.skinListBounds;
	}

	public void showPane(boolean isMain, Skin skin) {
		if (!isMain) {
			this.keeper.changeSkin(this.keeper.getCurrentSkin(), false);
			this.confirmPane.updateBackground(skin, this.mainPane);
		}

		this.mainCardLayout.show(this.popup, isMain ? this.mainPane.getName()
				: this.confirmPane.getName());
	}

	@Override
	@Deprecated
	public void updateUI() {
	}

	private static class SkinMenuUI extends BasicMenuUI {
		public static ComponentUI createUI(JComponent c) {
			return new SkinMenuUI();
		}

		@Override
		protected MouseInputListener createMouseInputListener(JComponent c) {
			return new MouseInputHandler();
		}

		protected class MouseInputHandler extends BasicMenuUI.MouseInputHandler {
			protected MouseInputHandler() {
				super();
			}

			@Override
			public void mouseEntered(MouseEvent evt) {
				((JMenu) evt.getSource()).getModel().setRollover(true);
			}

			@Override
			public void mouseExited(MouseEvent evt) {
				((JMenu) evt.getSource()).getModel().setRollover(false);
			}
		}
	}
}